package system_configures

import (
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/service/app"
)

// 查询参数
type QueryParams struct {
	PageSize  string `form:"page_size"  binding:"gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index"  binding:"gte=0,lte=99999" label:"当前页数"`
}

// add 参数
type AddParams struct {
	Sign  string `form:"sign" binding:"" label:"标识"`
	Sort  int    `form:"sort" label:"排序"`
	Title string `form:"title"  binding:"required,min=2,max=32" label:"标题"`
	Value string `form:"value" label:"值"`
	Pid   int64  `form:"pid" binding:"" label:"上级配置"`
	Mark  string `form:"mark"  binding:"" label:"描述"`
}

// 配置数据类型
var ConfigureType = []map[string]string{
	{
		"type":  "empty",
		"title": "空值",
	},
	{
		"type":  "string",
		"title": "字符串",
	},
	{
		"type":  "int",
		"title": "数字",
	},
	{
		"type":      "array_1",
		"title":     "数组(,)",
		"separator": ",",
	},
	{
		"type":      "array_2",
		"title":     "数组(|)",
		"separator": "|",
	},
	{
		"type":      "array_3",
		"title":     "数组(-)",
		"separator": "-",
	},
	{
		"type":  "bool",
		"title": "布尔",
	},
}

// 返回的数据结构 列表树
type configureListData struct {
	Id       int64
	Title    string
	Sign     string
	Value    string
	Pid      int64
	Mark     string
	Status   bool
	Sort     int
	Children []*configureListData
}

// 分页获取所有数据
// @param params map 参数
// @return interface{}, error
func GetDataList(params map[string]interface{}) ([]*configureListData, error) {

	queryParams, errBuild := model.BuildAdminQueryParam(params)
	if errBuild != nil {
		return nil, app.NewError(errBuild)
	}

	query := app.Db().Desc("id").Limit(queryParams.Limit, queryParams.Offset)

	data := make([]*SystemConfigures, 0)
	// 求总条数
	err := query.Find(&data)
	if err != nil {
		return nil, app.NewError(err)
	}

	returnData := BuildConfigureListTree(data, 0)

	return returnData, nil
}

// 获取数据 通过ID
func GetItemById(id int64) (*SystemConfigures, error) {
	item := new(SystemConfigures)

	has, err := app.Db().ID(id).Get(item)

	if err != nil {
		return nil, err
	} else {
		if !has {
			return item, nil
		}
	}

	return item, nil
}

// 获取数据 通过 sign
func GetItemBySign(sign string) (*SystemConfigures, error) {
	item := new(SystemConfigures)

	has, err := app.Db().Where("sign = ?", sign).Get(item)

	if err != nil {
		return nil, err
	} else {
		if !has {
			return item, nil
		}
	}

	return item, nil
}

// 添加 / 更新 管理
// 不用反射合并结构体
func (pc *SystemConfigures) AddOrUpdatePartnerConfigure(params AddParams) (*SystemConfigures, error) {

	var affected int64
	var errInsert error

	// 如果指定了上级 检测PID
	parentConfigure := new(SystemConfigures)
	if params.Pid > 0 {
		has, errParent := app.Db().ID(params.Pid).Get(parentConfigure)
		if errParent != nil {
			return nil, app.NewError(errParent)
		}

		if !has {
			return nil, app.NewError("对不起, PID无效")
		}
	}

	// 检测sign 唯一性
	if pc.Id == 0 {
		if IsFiledValueUnique("sign", params.Sign) {
			return nil, app.NewError("对不起, sign值已经存在")
		}
	} else {
		if pc.Sign != params.Sign {
			if IsFiledValueUniqueExcept("sign", params.Sign, pc.Sign) {
				return nil, app.NewError("对不起, sign值已经存在")
			}
		}
	}

	if pc != nil && pc.Id > 0 {
		// 更新数据
		pc.Sign = params.Sign
		pc.Title = params.Title
		pc.Sort = params.Sort
		pc.Value = params.Value
		pc.Mark = params.Mark

		affected, errInsert = app.Db().ID(pc.Id).Update(pc)

		if errInsert != nil {
			return nil, app.NewError(errInsert)
		}
	} else {
		// 计算上一个菜单的ID
		lastMenu := new(SystemConfigures)
		has, errLast := app.Db().Where("pid = ?", params.Pid).Desc("id").Get(lastMenu)
		if errLast != nil {
			return nil, app.NewError(errLast)
		}

		var newId int64 = 1000
		var sort int = 0
		if has {
			if params.Pid > 0 {
				newId = lastMenu.Id + 1
			} else {
				newId = lastMenu.Id + 1000
			}

			sort = lastMenu.Sort + 1
		} else {
			if params.Pid > 0 {
				newId = params.Pid + 1
				sort = 0
			}
		}

		// 插入数据
		pc.Id = newId
		pc.Sign = params.Sign
		pc.Title = params.Title
		pc.Sort = sort
		pc.Value = params.Value
		pc.Mark = params.Mark
		pc.Pid = params.Pid
		pc.Status = true

		affected, errInsert = app.Db().Insert(pc)

		if errInsert != nil {
			return nil, app.NewError(errInsert)
		}

		if affected != 1 {
			return nil, app.NewError("新增菜单错误(0x001)")
		}
	}

	return pc, nil
}

// @title BuildConfigureListTree
// @description 关系树　列表页使用
func BuildConfigureListTree(sourceData []*SystemConfigures, pid int64, levelArgs ...int) []*configureListData {
	deep := 2
	if len(levelArgs) > 0 {
		deep = levelArgs[0]
	}

	deep--

	buildData := make([]*configureListData, 0)

	for _, item := range sourceData {
		if item.Pid == pid {
			data := configureListData{
				Id:       item.Id,
				Title:    item.Title,
				Sign:     item.Sign,
				Value:    item.Value,
				Pid:      item.Pid,
				Mark:     item.Mark,
				Status:   item.Status,
				Sort:     item.Sort,
				Children: make([]*configureListData, 0),
			}

			if deep > 0 {
				data.Children = BuildConfigureListTree(sourceData, item.Id, deep)
			}

			buildData = append(buildData, &data)
		}
	}

	return buildData
}

/** =============================  辅助函数 ============================= */
// 检测字段唯一性
func IsFiledValueUnique(field string, value interface{}) bool {
	user := new(SystemConfigures)

	has, err := app.Db().Where(field+" = ?", value).Get(user)

	if err != nil {
		return false
	} else {
		if !has {
			return false
		}
	}

	return true
}

// 检测字段唯一性 处理莫个特殊
func IsFiledValueUniqueExcept(field string, value interface{}, except interface{}) bool {
	model := new(SystemConfigures)

	has, err := app.Db().Where(field+" = ?", value).Get(model)

	if err != nil {
		return false
	} else {
		if !has {
			return false
		}
	}

	// 排除指定值
	if model.Sign == except {
		return false
	}

	return true
}

// 获取类型
func GetConfigureTypeItem(configureType string) map[string]string {
	for _, item := range ConfigureType {
		if item["type"] == configureType {
			return item
		}
	}
	return nil
}
